package com.itheima.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.hankcs.algorithm.AhoCorasickDoubleArrayTrie;
import com.itheima.admin.dto.WmNewsContentNodeDto;
import com.itheima.admin.mapper.AdChannelMapper;
import com.itheima.admin.mapper.AdSensitiveMapper;
import com.itheima.admin.pojo.AdChannel;
import com.itheima.admin.pojo.AdSensitive;
import com.itheima.admin.service.WemediaNewsAutoScanService;
import com.itheima.article.dto.ArticleInfoDto;
import com.itheima.article.feign.ApArticleFeign;
import com.itheima.article.pojo.ApArticle;
import com.itheima.article.pojo.ApArticleConfig;
import com.itheima.article.pojo.ApArticleContent;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.ali.AliGreenScanner;
import com.itheima.common.vo.ResultVo;
import com.itheima.dfs.feign.DfsFeign;
import com.itheima.wemedia.feign.WmNewsFeign;
import com.itheima.wemedia.pojo.WmNews;
import com.itheima.wemedia.vo.WmNewsVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    private WmNewsFeign wmNewsFeign;

    @Autowired
    private AdSensitiveMapper adSensitiveMapper;

    @Autowired
    private AliGreenScanner aliGreenScanner;

    @Autowired
    private ApArticleFeign apArticleFeign;

    @Autowired
    private AdChannelMapper adChannelMapper;

    @Autowired
    private DfsFeign dfsFeign;

    @Override
    public void autoScanWemediaNewsById(Long valueOf, String uuid) {
        //1. 通过文章id获取文章信息
        ResultVo<WmNews> wmNewsResultVo = wmNewsFeign.getWmNewsById(valueOf);
        WmNews wmNews = wmNewsResultVo.getData();
        //业务处理
        if (!wmNewsResultVo.isSuccess()) {
            log.error("【出错】文章自动审核：uuid={},id={} 远程调用查询文章失败", uuid, valueOf);
            throw new LeadNewsException("文章自动审核失败");
        }
        if (null == wmNews) {
            log.error("【出错】文章自动审核：uuid={},id={} 远程调用查询不到文章数据", uuid, valueOf);
            throw new LeadNewsException("文章自动审核失败");
        }
        if (wmNews.getStatus() != BusinessConstants.WmNewsConstants.STATUS_SUBMIT) {
            log.error("【出错】文章自动审核：uuid={},id={},status={} 文章状态不正确", uuid, valueOf, wmNews.getStatus());
            throw new LeadNewsException("文章自动审核失败");
        }
        //2. 抽取文本内容, 包含内容与标题
        String text = getTextFromWmNews(wmNews);

        WmNews update = new WmNews();
        update.setId(wmNews.getId());
        //3. 敏感词检测
        Map<String, String> scanResult = new HashMap<>();
        if (sensitiveWordCheck(text)) {
            log.info("文章自动审核：uuid={},id={} 包含敏感词", uuid, valueOf);
            update.setReason("文章包含敏感词" + uuid);
        } else {
            //4. 文本反垃圾审核 调用aliyun工具
            try {
                scanResult = aliGreenScanner.greenTextScan(text);
                if (null == scanResult) {
                    log.error("【出错】文章自动审核：uuid={},id={} 调用aliyun文本反垃圾出错", uuid, valueOf);
                    return;
                }
            } catch (Exception e) {
                log.error("【出错】文章自动审核：uuid={},id={} 调用阿里反垃圾失败", uuid, valueOf);
                return;
            }
        }
        if (BusinessConstants.ScanConstants.PASS.equals(scanResult.get("suggestion"))) {
            //5. 提取图片内容
            List<String> imageList = getImageListFromWmNews(wmNews);
            if (!CollectionUtils.isEmpty(imageList)) {
                //下载文件
                ResultVo<List<byte[]>> downloadResultVo = dfsFeign.download(imageList);
                List<byte[]> imageDataList = downloadResultVo.getData();
                if (!downloadResultVo.isSuccess() || CollectionUtils.isEmpty(imageDataList)) {
                    log.error("【出错】文章自动审核：uuid={},id={} 远程调用下载文章图片失败", uuid, valueOf);
                    return;
                }
                //6. 图片反垃圾审核 调用aliyun工具
                try {
                    scanResult = aliGreenScanner.imageScan(imageDataList);
                    if (null == scanResult) {
                        log.error("【出错】文章自动审核：uuid={},id={} 调用aliyun图片审核失败", uuid, valueOf);
                        return;
                    }
                    //审核结果解析
                    String suggestion = scanResult.get("suggestion");
                    switch (suggestion) {
                        case BusinessConstants.ScanConstants.PASS:
                            update
                                    .setStatus(BusinessConstants.WmNewsConstants.STATUS_PASS);
                            break;
                        case BusinessConstants.ScanConstants.REVIEW:
                            update
                                    .setStatus(BusinessConstants.WmNewsConstants.STATUS_MANUAL);
                            break;
                        case BusinessConstants.ScanConstants.BLOCK:
                            update
                                    .setStatus(BusinessConstants.WmNewsConstants.STATUS_BLOCK);
                            break;

                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //7. 更新文章审核状态
        log.info("文章自动审核结果：uuid={},id={},status={}",uuid,valueOf, update.getStatus());
        ResultVo<WmNews> resultVo = wmNewsFeign.update(update);
        if(resultVo.isSuccess()){
            log.info("文章自动审核结果更新成功：uuid={},id={},status={}",uuid,valueOf, update.getStatus());
        }else{
            log.info("文章自动审核结果更新失败：uuid={},id={},status={}",uuid,valueOf, update.getStatus());
        }
    }

    /**
     * 同步文章数据
     * @param wmNewsVo
     * @return
     */
    @Override
    public boolean syncArticleInfo(WmNewsVo wmNewsVo) {
      //1.构建articleInfo
        ArticleInfoDto articleInfoDto = new ArticleInfoDto();
        //2.构建文章信息
        ApArticle apArticle = buildApArticle(wmNewsVo);
        articleInfoDto.setApArticle(apArticle);

        //3.构建文章内容对象
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setContent(wmNewsVo.getContent());
        articleInfoDto.setApArticleContent(apArticleContent);

        //4.构建文章配置对象
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setIsDown(0);
        apArticleConfig.setIsDelete(0);// 0:未删除
        apArticleConfig.setIsForward(1);
        apArticleConfig.setIsComment(1);
        articleInfoDto.setApArticleConfig(apArticleConfig);

        //5.自媒体文章id
        articleInfoDto.setWmNewsId(wmNewsVo.getId());

        //app用户id
        articleInfoDto.setApUserId(wmNewsVo.getApUserId());

        //6.远程调用文章微服务保存文章信息
        ResultVo resultVo = apArticleFeign.saveArticleInfo(articleInfoDto);

        //7.解析返回结果
        return resultVo.isSuccess();
    }

    /**
     * 设置文章数据
     * @param wmNewsVo
     * @return
     */
    private ApArticle buildApArticle(WmNewsVo wmNewsVo) {
        ApArticle apArticle = new ApArticle();
        //复制属性
        BeanUtils.copyProperties(wmNewsVo,apArticle);
        apArticle.setId(null);
        //修改文章时，删除旧有的已发布的文章
        apArticle.setId(wmNewsVo.getArticleId());
        //作者id
        apArticle.setAuthorId(wmNewsVo.getApUserId());
        //作者名称
        apArticle.setAuthorName(wmNewsVo.getAuthorName());
        //频道名称
        Integer channelId = wmNewsVo.getChannelId();
        AdChannel adChannel = adChannelMapper.selectById(channelId);
        apArticle.setChannelName(adChannel.getName());
        //设置其他属性
        apArticle.setLayout(wmNewsVo.getType());
        apArticle.setFlag(0);//0：普通文章
        apArticle.setLikes(0);
        apArticle.setCollection(0);
        apArticle.setComment(0);
        apArticle.setViews(0);
        apArticle.setProvinceId(0);
        apArticle.setCityId(0);
        apArticle.setCountyId(0);
        apArticle.setSyncStatus(0);//0：未同步给es
        apArticle.setOrigin(1);//1.自媒体 2.爬虫
        return apArticle;

    }

    private List<String> getImageListFromWmNews(WmNews wmNews) {
        List<WmNewsContentNodeDto> nodeDtoList = JSON.parseArray(wmNews.getContent(), WmNewsContentNodeDto.class);
        List<String> imagesList = nodeDtoList.stream().filter(node -> BusinessConstants.WmNewsConstants.CONTENT_IMAGE.equals(node.getType()))
                .map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        if (!StringUtils.isEmpty(imagesList)) {
            String[] split = wmNews.getImages().split(",");
            Collections.addAll(imagesList, split);
        }
        return imagesList;
    }

    /**
     * 敏感词检测
     *
     * @param text
     * @return
     */
    private boolean sensitiveWordCheck(String text) {
        //获取数据库中的敏感词
        List<AdSensitive> sensitiveList = adSensitiveMapper.selectList(null);
        if (CollectionUtils.isEmpty(sensitiveList)) {
            return false;
        }
        //转成map
        Map<String, String> map = sensitiveList.stream().collect(Collectors.toMap(AdSensitive::getSensitives, AdSensitive::getSensitives));
        //构建成字典树
        AhoCorasickDoubleArrayTrie<String> trie = new AhoCorasickDoubleArrayTrie<String>();
        trie.build(map);

        return trie.findFirst(text) != null;

    }

    /**
     * 抽取文本内容
     *
     * @param wmNews
     * @return
     */
    private String getTextFromWmNews(WmNews wmNews) {
        // 转化json字符串为文章内容节点数据
        List<WmNewsContentNodeDto> contentList = JSON.parseArray(wmNews.getContent(), WmNewsContentNodeDto.class);
        //提取type=text中的value
        List<String> collects = contentList.stream().filter(n ->
                BusinessConstants.WmNewsConstants.CONTENT_TEXT.equals(n.getType())
        ).map(WmNewsContentNodeDto::getValue).collect(Collectors.toList());
        //添加标题
        collects.add(wmNews.getTitle());
        //以逗号分割并拼接起来
        String text = String.join(",", collects);
        return text;
    }

}
